﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;

namespace Cobit5.BIZ.MemberShip
{
    public class Membership
    {
        #region Model
        private string _userid;
        private string _username;
        private string _password;
        private string _passwordsalt;
        private string _email;
        private string _mobile;
        private string _telephone;
        private string _passwordquestion;
        private string _passwordanswer;
        private bool _isapproved;
        private bool _islockedout;
        private DateTime? _createdate;
        private DateTime? _lastlogindate;
        private DateTime? _lastpasswordchangeddate;
        private DateTime? _lastlockoutdate;
        private int? _failedpasswordattemptcount;
        private DateTime? _failedpasswordattemptwindowstart;
        private int? _failedpasswordanswerattemptcount;
        private DateTime? _failedpasswordanswerattemptwindowsstart;
        private string _comment;
        /// <summary>
        /// 
        /// </summary>
        public string UserId
        {
            set { _userid = value; }
            get { return _userid; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string UserName
        {
            set { _username = value; }
            get { return _username; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string Password
        {
            set { _password = value; }
            get { return _password; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string PasswordSalt
        {
            set { _passwordsalt = value; }
            get { return _passwordsalt; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string Email
        {
            set { _email = value; }
            get { return _email; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string Mobile
        {
            set { _mobile = value; }
            get { return _mobile; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string Telephone
        {
            set { _telephone = value; }
            get { return _telephone; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string PasswordQuestion
        {
            set { _passwordquestion = value; }
            get { return _passwordquestion; }
        }
        /// <summary>
        /// 
        /// </summary>
        public string PasswordAnswer
        {
            set { _passwordanswer = value; }
            get { return _passwordanswer; }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool IsApproved
        {
            set { _isapproved = value; }
            get { return _isapproved; }
        }
        /// <summary>
        /// 
        /// </summary>
        public bool IsLockedOut
        {
            set { _islockedout = value; }
            get { return _islockedout; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? CreateDate
        {
            set { _createdate = value; }
            get { return _createdate; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? LastLoginDate
        {
            set { _lastlogindate = value; }
            get { return _lastlogindate; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? LastPasswordChangedDate
        {
            set { _lastpasswordchangeddate = value; }
            get { return _lastpasswordchangeddate; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? LastLockoutDate
        {
            set { _lastlockoutdate = value; }
            get { return _lastlockoutdate; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int? FailedPasswordAttemptCount
        {
            set { _failedpasswordattemptcount = value; }
            get { return _failedpasswordattemptcount; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? FailedPasswordAttemptWindowStart
        {
            set { _failedpasswordattemptwindowstart = value; }
            get { return _failedpasswordattemptwindowstart; }
        }
        /// <summary>
        /// 
        /// </summary>
        public int? FailedPasswordAnswerAttemptCount
        {
            set { _failedpasswordanswerattemptcount = value; }
            get { return _failedpasswordanswerattemptcount; }
        }
        /// <summary>
        /// 
        /// </summary>
        public DateTime? FailedPasswordAnswerAttemptWindowsStart
        {
            set { _failedpasswordanswerattemptwindowsstart = value; }
            get { return _failedpasswordanswerattemptwindowsstart; }
        }
        /// <summary>
        /// Administrator,
        ///Auditor,
        ///Professional
        /// </summary>
        public string Comment
        {
            set { _comment = value; }
            get { return _comment; }
        }
        #endregion Model

        #region MembershipFunction

        /// <summary>
        /// Initialize
        /// </summary>
        public Membership(string in_userID)
        {
            if (Membership.ExistMembership(in_userID) == 0)
                return;

            Model.Membership myMember = new Model.Membership();
            DAL.Membership optMember = new DAL.Membership();
            myMember = optMember.GetModel(in_userID);

            this._userid = myMember.UserId;
            this._username = myMember.UserName;
            this._password = myMember.Password;
            this._passwordsalt = myMember.PasswordSalt;
            this._email = myMember.Email;
            this._mobile = myMember.Mobile;
            this._telephone = myMember.Telephone;
            this._passwordquestion = myMember.PasswordQuestion;
            this._passwordanswer = myMember.PasswordAnswer;
            this._isapproved = myMember.IsApproved;
            this._islockedout = myMember.IsLockedOut;
            this._createdate = myMember.CreateDate;
            this._lastlogindate = myMember.LastLoginDate;
            this._lastpasswordchangeddate = myMember.LastPasswordChangedDate;
            this._lastlockoutdate = myMember.LastLockoutDate;
            this._failedpasswordattemptcount = myMember.FailedPasswordAnswerAttemptCount;
            this._failedpasswordattemptwindowstart = myMember.FailedPasswordAttemptWindowStart;
            this._failedpasswordanswerattemptcount = myMember.FailedPasswordAnswerAttemptCount;
            this._failedpasswordanswerattemptwindowsstart = myMember.FailedPasswordAnswerAttemptWindowsStart;
            this._comment = myMember.Comment;
        }

        /// <summary>
        /// Count the number of Member
        /// </summary>
        public static int CountAllMember()
        {
            DAL.Membership optMember = new DAL.Membership();
            return optMember.GetRecordCount("1=1");
        }

        /// <summary>
        /// List all the Member in pages
        /// </summary>
        public static List<Membership> GetAllMembership(string in_orderby, int in_startIndex, int in_endIndex)
        {
            DAL.Membership optMember = new DAL.Membership();
            DataSet ds = optMember.GetListByPage("1=1", in_orderby, in_startIndex, in_endIndex);

            if (ds == null || ds.Tables[0].Rows.Count < 1)
                return null;

            List<Membership> returnMembership = new List<Membership>();
            for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                Membership newMember = new Membership(ds.Tables[0].Rows[i]["UserId"].ToString());
                returnMembership.Add(newMember);
            }

            return returnMembership;
        }

        /// <summary>
        /// Check if the Member exists
        /// Return  1:Exist;
        ///         0:Not Exist;
        /// </summary>
        public static int ExistMembership(string in_userID)
        {
            DAL.Membership optMember = new DAL.Membership();
            if (!optMember.Exists(in_userID))
                return 0;
            else return 1;
        }

        /// <summary>
        /// Create a new Memebership
        /// Return  1.Success
        ///         2.Id already existed
        ///         3.DAL Error
        /// Comment: Administrator,Auditor,Professional
        /// </summary>
        public static int CreateMembership(string in_userID, string in_userName, string in_password, string in_passwordSalt, string in_email, string in_mobile, string in_telephone, string in_passwordQuestion, string in_passwordAnswer, string in_comment)
        {
            if (Membership.ExistMembership(in_userID) == 1)
                return 2;

            Model.Membership myMember = new Model.Membership();
            myMember.UserId = in_userID;
            myMember.UserName = in_userName;
            myMember.Password = Common.Cobit_SHA256.GetSHA256(in_password + in_passwordSalt);
            myMember.PasswordSalt = in_passwordSalt;
            myMember.Email = in_email;
            myMember.Mobile = in_mobile;
            myMember.Telephone = in_telephone;
            myMember.PasswordQuestion = in_passwordQuestion;
            myMember.PasswordAnswer = in_passwordAnswer;

            myMember.IsApproved = false;
            myMember.IsLockedOut = true;
            myMember.CreateDate = DateTime.Now;
            myMember.Comment = in_comment;

            DAL.Membership optMember = new DAL.Membership();
            bool ok = optMember.Add(myMember);
            if (!ok) return 3;
            else return 1;
        }

        /// <summary>
        /// Update the Membership
        /// Return: 1.Success
        ///         2.DAL Error
        /// </summary>
        public int UpdateMembership()
        {
            Model.Membership myMembership = new Model.Membership();
            myMembership.UserId = this._userid;
            myMembership.UserName = this._username;
            myMembership.Password = Common.Cobit_SHA256.GetSHA256(this._password + this._passwordsalt);
            myMembership.PasswordSalt = this._passwordsalt;
            myMembership.Email = this._email;
            myMembership.Mobile = this._mobile;
            myMembership.Telephone = this._telephone;
            myMembership.PasswordQuestion = this._passwordquestion;
            myMembership.PasswordAnswer = this._passwordanswer;
            myMembership.IsApproved = this._isapproved;
            myMembership.IsLockedOut = this._islockedout;
            myMembership.CreateDate = this._createdate;
            myMembership.LastLoginDate = this._lastlogindate;
            myMembership.LastPasswordChangedDate = this._lastpasswordchangeddate;
            myMembership.LastLockoutDate = this._lastlockoutdate;
            myMembership.FailedPasswordAnswerAttemptCount = this._failedpasswordanswerattemptcount;
            myMembership.FailedPasswordAnswerAttemptWindowsStart = this._failedpasswordanswerattemptwindowsstart;
            myMembership.FailedPasswordAttemptCount = this._failedpasswordattemptcount;
            myMembership.FailedPasswordAttemptWindowStart = this._failedpasswordattemptwindowstart;
            myMembership.Comment = this._comment;

            DAL.Membership optMembership = new DAL.Membership();
            bool ok = optMembership.Update(myMembership);
            if (!ok) return 2;
            else return 1;
        }

        /// <summary>
        /// 尚待建设
        /// </summary>
        public static int DeleteMembership(string in_userID)
        {
            return 0;
        }

        #endregion MembershipFunction

        #region Membership-RACIRole

        /// <summary>
        /// Get the number of RACIRole this Member has
        /// </summary>
        public int CountRACIRole()
        {
            DAL.RACI_Body optRACI = new DAL.RACI_Body();
            return optRACI.GetRecordCount("userID='" + this._userid + "'");
        }

        /// <summary>
        /// Get the list of RACIRole
        /// Parameters: 1.in_orderBy:"roleID"
        /// </summary>
        public List<Cobit.RACIRole> RACIRoles(string in_orderBy, int in_startIndex, int in_endIndex)
        {
            DAL.RACI_Body optRACI_Body = new DAL.RACI_Body();
            DataSet ds = optRACI_Body.GetListByPage("userID='" + this._userid + "'", in_orderBy, in_startIndex, in_endIndex);
            if (ds == null || ds.Tables[0].Rows.Count < 1)
                return null;

            List<Cobit.RACIRole> returnRACIRoles = new List<Cobit.RACIRole>();
            for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                Cobit.RACIRole newRACIRole = new Cobit.RACIRole(int.Parse(ds.Tables[0].Rows[i]["roleID"].ToString()));
                returnRACIRoles.Add(newRACIRole);
            }

            return returnRACIRoles;
        }

        /// <summary>
        /// Add a RACIRole to this Member
        /// Parameters: 1.in_roleID: RACIRole id
        /// 
        /// Return: 2.RACIRole ID not exists
        ///         3.Error in DAL
        ///         1.Success
        /// </summary>
        public int AddRACIRole(int in_roleID)
        {
            if (Cobit.RACIRole.ExistRACIRole(in_roleID) == 0)
                return 2;

            Model.RACI_Body myRACI_Body = new Model.RACI_Body();
            myRACI_Body.roleID = in_roleID;
            myRACI_Body.userID = this._userid;

            DAL.RACI_Body optRACI_Body = new DAL.RACI_Body();
            bool ok = optRACI_Body.Add(myRACI_Body);
            if (!ok) return 3;
            else return 1;
        }

        /// <summary>
        /// Remove a RACIRole from this Member
        /// Parameters: 1.in_roldID: RACIRole id
        /// Return: 2.RACI_Role not exists
        ///         3.Error in DAL
        ///         1.Success
        /// </summary>
        public int RemoveRACIRole(int in_roleID)
        {
            if (Cobit.RACIRole.ExistRACIRole(in_roleID) == 0)
                return 2;

            DAL.RACI_Body optRACI_Body = new DAL.RACI_Body();
            bool ok = optRACI_Body.Delete(in_roleID, this._userid);
            if (!ok) return 3;
            else return 1;
        }

        #endregion Membership-RACIRole

        /// <summary>
        /// 
        /// 0.该用户Id不存在
        /// 1.登录成功
        /// 2.该用户Id尚未被开通激活
        /// 3.该用户Id被锁定了
        /// 4.用户Id与密码不匹配
        /// 5.更新用户错误记录出错
        /// 6.登录成功，记录出错
        /// </summary>
        public static int LoginSystem(string in_UserId, string in_Password)
        {
            /*** If the UserId doesn't exist ***/
            DAL.Membership optMembership = new DAL.Membership();
            if (!optMembership.Exists(in_UserId))
                return 0;

            /*** Check: isApproved ***/
            Model.Membership objMembership = new Model.Membership();
            objMembership = optMembership.GetModel(in_UserId);
            if (objMembership.IsApproved == false)
                return 2;

            /*** Check: isLocked ***/
            if (objMembership.IsLockedOut == true)
                return 3;

            /*** Check: Password right or wrong ***/
            in_Password = Common.Cobit_SHA256.GetSHA256(in_Password + objMembership.PasswordSalt);
            if (in_Password != objMembership.Password)
            {
                /*** Incorrect Password, Add Count ***/
                if (objMembership.FailedPasswordAnswerAttemptCount == null || objMembership.FailedPasswordAnswerAttemptCount == 0)
                    objMembership.FailedPasswordAnswerAttemptCount = 1;
                else
                    objMembership.FailedPasswordAnswerAttemptCount += 1;

                /*** Count over the limit, then lock the account ***/
                Config.SystemSettings mySystemSettings = new Config.SystemSettings();
                if (objMembership.FailedPasswordAnswerAttemptCount >= mySystemSettings.PasswordTryTimes)
                {
                    objMembership.IsLockedOut = true;
                }

                bool ok = optMembership.Update(objMembership);
                if (!ok) return 5;

                return 4;
            }

            /*** Correct: Clear Account Fail Try Number ***/
            objMembership.FailedPasswordAnswerAttemptCount = 0;
            bool ok2 = optMembership.Update(objMembership);
            if (!ok2) return 6;

            return 1;
        }

        /*缺乏Membership.Delete方法*/
    }
}
